/**
 * The contents of this file are subject to the license and copyright detailed in the LICENSE and NOTICE files at the root of the source tree and available online at
 * http://www.askosi.org/license.html
 */
package be.destin.skos.core;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;

import org.apache.log4j.Logger;
import org.openrdf.model.Literal;
import org.openrdf.model.URI;
import org.openrdf.model.Value;
import org.openrdf.query.Binding;
import org.openrdf.query.BindingSet;
import org.openrdf.query.MalformedQueryException;
import org.openrdf.query.QueryEvaluationException;
import org.openrdf.query.QueryLanguage;
import org.openrdf.query.TupleQuery;
import org.openrdf.query.TupleQueryResult;
import org.openrdf.repository.RepositoryConnection;
import org.openrdf.repository.RepositoryException;

import be.destin.rdf.changes.Status;
import be.destin.util.Util;

public class SparqlSource {

	/** log4j category */
	private static Logger log = Logger.getLogger(SparqlSource.class);

	/*
	 *  FOR JENA:
	protected static QueryExecution prepareQuery(SparqlPool con, String sparql, String param) {
		if (param == null) param = "";
		sparql = Util.replaceAllNoRegExp(sparql,"[param]",param);
		log.debug("Param="+param+", SparQL="+sparql);
		Query query = QueryFactory.create(sparql);
		// initializing queryExecution factory with remote service.
		// **this actually was the main problem I couldn't figure out.**
		QueryExecution qexec = QueryExecutionFactory.sparqlService(con.getUrl(), query);
		return qexec;
	}
	 */
	/*
	 * // now creating query object
Query query = QueryFactory.create(queryString);
// initializing queryExecution factory with remote service.
// **this actually was the main problem I couldn't figure out.**
QueryExecution qexec = QueryExecutionFactory.sparqlService("http://dbpedia.org/sparql", query);

//after it goes standard query execution and result processing which can
// be found in almost any Jena/SPARQL tutorial.
try {
    ResultSet results = qexec.execSelect();
    for (; results.hasNext();) {
        {
            QuerySolution soln = results.nextSolution() ;
            String x = soln.get("Concept").toString();
            System.out.print(x +"\n");
        }

    // Result processing is done here.
    }
}
finally {
   qexec.close();
}

	 */
	protected static void querySparqlMatch(RepositoryConnection con, ConceptScheme aScheme, String matchSQL, boolean local, String column, Method putMatch ) {
		if (matchSQL != null) {
			TupleQuery qexec = null;
			TupleQueryResult rs = null;
			try {
				qexec = con.prepareTupleQuery(QueryLanguage.SPARQL,  matchSQL);
				// setMaxQueryTime(int maxQueryTime) 
				if (qexec != null) {
					rs = qexec.evaluate();
					if (rs != null) {
						String currSchemePrefix = aScheme.getAbout()+SchemeInterface.separator;
						for (BindingSet soln = rs.next(); rs.hasNext(); soln = rs.next() ) {
							String currCode = getAbout(aScheme, soln, "about");
							if (currCode == null || currCode.isEmpty()) continue;

							//TODO: Chercher le matched scheme par sa racine d'URL...
							String currParent = getAbout(aScheme, soln, column);
							if (currParent == null || currParent.isEmpty()) continue;

							Concept entry;
							entry = aScheme.getConcept(currCode);
							if (entry == null && currCode.startsWith(currSchemePrefix)) {
								entry = aScheme.getConcept(currCode.substring(currSchemePrefix.length()+1));
							}
							if (entry == null) {
								String message = aScheme.getAbout() + SchemeInterface.separator + currCode
								+ " does not exist. Reffered for "+column+" "
								+ currParent;
								log.error(message);
								aScheme.getErrors().add(message);
							} else {

								if (local) {
									if (currParent.startsWith(currSchemePrefix)) {
										currParent = currParent.substring(currSchemePrefix.length());
										if (currParent.isEmpty()) continue;
									}
								} else {
									if (currParent.indexOf(SchemeInterface.separator) < 0) {
										String message = currCode + ": "+column+" \""+currParent+"\"is not prefixed with scheme code?";
										log.error(message);
										entry.addError(message);
										continue;
									}
								}

								Term aStatus = getString(aScheme,soln,"status",null);
								Status currStatus = null;
								if (aStatus != null) {
									currStatus = Status.valueOf(aStatus.getValue());
								}

								Term termQualifier = getString(aScheme, soln, "qual",null);
								String relQualifier = null;
								if (termQualifier != null) {
									relQualifier = termQualifier.getValue();
								}

								try {
									putMatch.invoke(entry, currParent, currStatus, relQualifier);
								} catch (IllegalArgumentException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								} catch (IllegalAccessException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								} catch (InvocationTargetException e) {
									// TODO Auto-generated catch block
									e.printStackTrace();
								}
							}
						}
					}
				}
			} catch (RepositoryException ex) {
				String message = aScheme.getAbout() + ", Connecting to SparQL repository to evaluate "+matchSQL+" : " + ex.getMessage();
				log.error(message);
				aScheme.getErrors().add(message);
			} catch (QueryEvaluationException ex) {
				String message = aScheme.getAbout() + ", Evaluating SparQL query "+matchSQL+" : " + ex.getMessage();
				log.error(message);
				aScheme.getErrors().add(message);
			} catch (MalformedQueryException ex) {
				String message = aScheme.getAbout() + ", Malformed SparQL query" + matchSQL + " : " + ex.getMessage();
				log.error(message);
				aScheme.getErrors().add(message);
			} finally {
				// No close for qexec ?
				if (rs != null) { // close Result
					try {
						rs.close();
					} catch (QueryEvaluationException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
		}
	}

	protected static void load(Properties properties, ConceptScheme aScheme, String configFile, Map<String, String> notationsDefinitions) {
		String dbPool = properties.getProperty("pool");

		SparqlPool pooledRepository = SparqlPool.getSparqlConnection(configFile,dbPool);
		if (pooledRepository == null) return;

		RepositoryConnection con = null;
		try {
			con = pooledRepository.getRepository().getConnection();
			// languages are deducted from the list of the languages of the list names
			// about, name-fr, name-en...,
			String namesSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.namesTable)); // SQL to get the names of the authority concepts

			// about, origin
			String aliassesSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.aliassesTable)); // SQL to
			// get the
			// aliasses of the
			// authority concepts
			// codes

			// about, language, synonym
			String synonymsSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.altTable)); // SQL to
			// get the
			// synonyms of the
			// authority concepts

			// languages are deducted from the list of the languages of the list names
			// about, note-fr, note-en...,
			String notesSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.notesTable)); // SQL to get the notes of the authority concepts

			// about, broader
			String parentsSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.parentsTable)); // SQL to get
			String relatedSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.relatedTable)); // SQL to get
			String broadMatchSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.broadMatchTable)); // SQL to get
			String relatedMatchSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.relatedMatchTable)); // SQL to get
			String exactMatchSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.exactMatchTable)); // SQL to get
			String closeMatchSQL = pooledRepository.substitute(aScheme,properties.getProperty(SqlSource.closeMatchTable)); // SQL to get

			if (namesSQL != null) {
				TupleQuery qexec = null;
				TupleQueryResult rs = null;
				try {
					qexec = con.prepareTupleQuery(QueryLanguage.SPARQL, namesSQL, null);
					if (qexec != null) {
						rs = qexec.evaluate();
						if (rs != null) {
							for (BindingSet soln = rs.next(); rs.hasNext(); soln = rs.next() ) {
								String currCode = getAbout(aScheme, soln, "about");
								if (currCode == null) continue;
								Concept entry = aScheme.findAbout_Concept(currCode);
								if (entry== null) {
									entry = Concept.ensure(aScheme,currCode);
									entry = aScheme.putConcept(currCode, entry);
								}

								Term aStatus = getString(aScheme,soln,"status",null);
								Status currStatus = null;
								if (aStatus != null) {
									currStatus = Status.valueOf(aStatus.getValue());
								}
                                Term aFormat = getString(aScheme,soln,"format",null);
                                TermFormat format = null;
                                if (aFormat != null) {
                                    format = TermFormat.valueOf(aFormat.getValue());
                                }
								Term aLang = getString(aScheme,soln,"lang",TermList.anyLanguage);
								String currLang = TermList.anyLanguage;
								if (aLang != null) {
									currLang = aLang.getValue().trim();
								}
								Term aTerm = getTerm(aScheme,soln,"label",currLang,"source");
								if (aTerm != null) {
									entry.putLabel(aTerm.getLang(), aTerm.getCurrentFormat(format), aTerm.getValue(), aTerm.getSource(), currStatus);
								}
								aTerm = getString(aScheme,soln,SchemeFactory.iconRoot,currLang);
								if (aTerm != null) {
									entry.putIcon(aTerm.getLang(), aTerm.getValue());
								}
								aTerm = getString(aScheme,soln,"url",currLang);
								if (aTerm != null) {
									entry.putUrl(aTerm.getLang(), aTerm.getValue());
								}

								aTerm = getString(aScheme,soln,"note",currLang);
								if (aTerm != null) {
									entry.putScopeNote(aTerm.getLang(), aTerm.getCurrentFormat(format), aTerm.getValue(), currStatus);
								}

								for (Term nameLang : aScheme.getTitle()) {
									String defLang = nameLang.getLang();
									aTerm = getString(aScheme,soln,"status-"+defLang,null);
									Status currLStatus = currStatus;
									if (aTerm != null) {
										currStatus = Status.valueOf(aTerm.getValue());
									}
	                                aTerm = getString(aScheme,soln,"format-"+defLang,null);
	                                TermFormat lFormat = format;
	                                if (aTerm != null) {
	                                    lFormat = TermFormat.valueOf(aTerm.getValue());
	                                }
									aTerm = getTerm(aScheme, soln, "label-" + defLang, defLang, "source-" + defLang);
									if (aTerm != null) {
										entry.putLabel(aTerm.getLang(), aTerm.getCurrentFormat(lFormat), aTerm.getValue(), aTerm.getSource(), currLStatus);
									}
									aTerm = getString(aScheme, soln, "note-" + defLang, defLang);
									if (aTerm != null) {
										entry.putScopeNote(aTerm.getLang(),  aTerm.getCurrentFormat(lFormat), aTerm.getValue(), currLStatus);
									}
									aTerm = getString(aScheme, soln, SchemeFactory.iconRoot+'-' + defLang, defLang);
									if (aTerm != null) {
										entry.putIcon(aTerm.getLang(), aTerm.getValue());
									}
									aTerm = getString(aScheme, soln, "url-" + defLang, defLang);
									if (aTerm != null) {
										entry.putUrl(aTerm.getLang(), aTerm.getValue());
									}
								}

							}
						}
					}
				} catch (Exception ex) {
					String message = aScheme.getAbout() + ", SparQL=" + namesSQL;
					log.error(message);
					aScheme.getErrors().add(message);
					Util.printStack(ex);

				} finally {
					// No close for qexec ?
					if (rs != null) { // close Result
						rs.close();
					}
				}
			}
			/*
			if (notesSQL != null) {
				try {
					log.debug(notesSQL);
					// create and execute a SELECT
					ResultSet rs = execQuery(con,notesSQL);

					while (rs.next()) {
						String currLang = TermList.anyLanguage;
						String currCode = getAbout(aScheme, rs, "about");
						if (currCode == null) continue;
						Concept entry = aScheme.findAbout_Concept(currCode);
						if (entry== null) {
							entry = Concept.ensure(aScheme,currCode);
							aScheme.putConcept(currCode, entry);
						}
						// get current row values
						try {
							String aLang = rs.getLabel("lang");
							if (aLang != null && aLang.length() > 0) {
								currLang = aLang;
							}
						} catch (java.sql.SQLException ex) { // a column may
							// be missing
							// for a given
							// language
						}
						// get current row values
						try {
							String aName = rs.getLabel("note");
							if (aName != null && aName.length() > 0) {
								// log.debug(currLang+"=="+aName);
								entry.putScopeNote(currLang, aName);
							}
						} catch (java.sql.SQLException ex) { // a column may
							// be missing
							// for a given
							// language
						}
						for (Term nameLang : aScheme.getTitle()) {
							try {
								String aNote = rs.getLabel("note-" + nameLang.getLang());
								if (aNote != null && aNote.length() > 0) {
									// log.debug(nameLang+"="+aName);
									entry.putScopeNote(nameLang.getLang(), aNote);
								}
							} catch (java.sql.SQLException ex) { // a column may
								// be missing
								// for a given
								// language
							}
						}
					}
					// close statement
					stmt.close();
				} catch (SQLException ex) {
					String message = aScheme.getAbout() + ", SQL=" + notesSQL + " : " + ex.toString()+"="+ex.getSQLState();
					log.error(message);
					aScheme.getErrors().add(message);
					Util.printStack(ex);
				}
			}
			if (aliassesSQL != null) {
				try {
					log.debug(aliassesSQL);
					ResultSet rs = execQuery(con,aliassesSQL);

					while (rs.next()) {
						String currCode = getAbout(aScheme,rs,"about");
						if (currCode == null) continue;

						String currOrigin = getAbout(aScheme,rs,"alias");
						if (currOrigin == null) continue;

						Concept entry = aScheme.getConcept(currCode);
						if (entry == null) {
							String message = aScheme.getAbout() + SchemeInterface.separator + currCode
											+ " does not exist. Reffered from "
											+ currOrigin;
							log.error(message);
							aScheme.getErrors().add(message);
						}
						aScheme.putAlias(currOrigin, currCode);
					}
					// close statement
					stmt.close();
				} catch (Exception ex) {
					String message = aScheme.getAbout() + ", SQL=" + aliassesSQL + " : " + ex.toString();
					log.error(message);
					aScheme.getErrors().add(message);
					Util.printStack(ex);
				}
			}
			 */
			if (synonymsSQL != null) {
				TupleQuery qexec = null;
				TupleQueryResult rs = null;
				try {
					qexec = con.prepareTupleQuery(QueryLanguage.SPARQL, synonymsSQL, null);
					if (qexec != null) {
						rs = qexec.evaluate();
						if (rs != null) {
							for (BindingSet soln = rs.next(); rs.hasNext(); soln = rs.next() ) {
								String currCode = getAbout(aScheme, soln, "about");
								if (currCode == null) continue;
								Concept entry = aScheme.findAbout_Concept(currCode);
								if (entry== null) {
									String message = aScheme.getAbout() + SchemeInterface.separator + currCode
											+ " does not exist to add a synonym.";
									log.error(message);
									aScheme.getErrors().add(message);
									continue;
								}

								Term aStatus = getString(aScheme,soln,"status",null);
								Status currStatus = null;
								if (aStatus != null) {
									currStatus = Status.valueOf(aStatus.getValue());
								}
                                Term aFormat = getString(aScheme,soln,"format",null);
                                TermFormat format = null;
                                if (aFormat != null) {
                                    format = TermFormat.valueOf(aFormat.getValue());
                                }
								Term aLang = getString(aScheme,soln,"lang",TermList.anyLanguage);
								String currLang = TermList.anyLanguage;
								if (aLang != null) {
									currLang = aLang.getValue().trim();
								}
								Term aPossibleHide = getString(aScheme,soln,"hidden",TermList.anyLanguage);
								String possHide = null;
								if (aPossibleHide != null) {
									possHide = aPossibleHide.getValue();
									if (possHide != null && !possHide.isEmpty()) {
										possHide = possHide.substring(0,1).toUpperCase();
									}
								}
								boolean hidden = false;
								if (possHide != null && !possHide.isEmpty() && !possHide.equals("0") && !possHide.equals("N") && !possHide.equals("F")) {
									hidden = true;
								}
								Term aTerm = getTerm(aScheme,soln,"label",currLang,"source");
								if (aTerm != null) {
									if (hidden) {
										entry.putHiddenLabel(aTerm.getLang(), aTerm.getCurrentFormat(format), aTerm.getValue(), aTerm.getSource(), currStatus);
									} else {
										entry.putAltLabel(aTerm.getLang(), aTerm.getCurrentFormat(format), aTerm.getValue(), aTerm.getSource(), currStatus);
									}
								}

								for (Term nameLang : aScheme.getTitle()) {
									String defLang = nameLang.getLang();
									aTerm = getString(aScheme,soln,"status-"+defLang,null);
									Status currLStatus = currStatus;
									if (aTerm != null) {
										currStatus = Status.valueOf(aTerm.getValue());
									}
	                                aTerm = getString(aScheme,soln,"format-"+defLang,null);
	                                TermFormat lFormat = format;
	                                if (aTerm != null) {
	                                    lFormat = TermFormat.valueOf(aTerm.getValue());
	                                }
									aTerm = getTerm(aScheme, soln, "label-" + defLang, defLang, "source-" + defLang);
									if (aTerm != null) {
										entry.putLabel(aTerm.getLang(), aTerm.getCurrentFormat(lFormat), aTerm.getValue(), aTerm.getSource(), currLStatus);
									}
								}

							}
						}
					}
				} catch (Exception ex) {
					String message = aScheme.getAbout() + ", SparQL=" + namesSQL;
					log.error(message);
					aScheme.getErrors().add(message);
					Util.printStack(ex);

				} finally {
					// No close for qexec ?
					if (rs != null) { // close Result
						rs.close();
					}
				}
			}

			try {
				querySparqlMatch(con,aScheme,parentsSQL,true,"broader",Concept.class.getMethod("putBroader",String.class,Status.class,String.class));
			} catch (NoSuchMethodException NSM) {
				log.error("broader: unknown relation");
			}
			try {
				querySparqlMatch(con,aScheme,relatedSQL,true,"related",Concept.class.getMethod("putRelated",String.class,Status.class,String.class));
			} catch (NoSuchMethodException NSM) {
				log.error("related: unknown relation");
			}
			try {
				querySparqlMatch(con,aScheme,broadMatchSQL,false,"broadmatch",Concept.class.getMethod("putBroadMatch",String.class,Status.class,String.class));
			} catch (NoSuchMethodException NSM) {
				log.error("broadmatch: unknown relation");
			}
			try {
				querySparqlMatch(con,aScheme,relatedMatchSQL,false,"relatedmatch",Concept.class.getMethod("putRelatedMatch",String.class,Status.class,String.class));
			} catch (NoSuchMethodException NSM) {
				log.error("relatedmatch: unknown relation");
			}
			try {
				querySparqlMatch(con,aScheme,exactMatchSQL,false,"exactmatch",Concept.class.getMethod("putExactMatch",String.class,Status.class,String.class));
			} catch (NoSuchMethodException NSM) {
				log.error("exactmatch: unknown relation");
			}
			try {
				querySparqlMatch(con,aScheme,closeMatchSQL,false,"closematch",Concept.class.getMethod("putCloseMatch",String.class,Status.class,String.class));
			} catch (NoSuchMethodException NSM) {
				log.error("closematch: unknown relation");
			}
		} catch (RepositoryException ex) {
			String message = aScheme.getAbout() + ", Connecting to SparQL repository: "+ex.getMessage();
			log.error(message);
			aScheme.getErrors().add(message);
		} catch (QueryEvaluationException ex) {
			String message = aScheme.getAbout() + ", Evaluating SparQL query: "+ex.getMessage();
			log.error(message);
			aScheme.getErrors().add(message);
		} 
		finally {
			if (con != null) 
				try {
					con.close();
				} catch (RepositoryException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
		}
		/*
			String aProp = null;
			if (notationsDefinitions.size() > 0) {
				TermList languages = aScheme.getTitle();
				for (String indexCode : notationsDefinitions.keySet()) {
					NotationScheme subList = (NotationScheme) aScheme.getManagerInstance().getScheme(indexCode);
					for (Term language : languages) {
						aProp = properties.getProperty(SchemeFactory.titleRoot + "." + indexCode
								+ "-" + language);
						if (aProp != null && aProp.length() > 0)
							subList.putTitle(aProp, language.getLang());
						aProp = properties.getProperty(SchemeFactory.descriptionRoot + "." + indexCode
								+ "-" + language);
						if (aProp != null && aProp.length() > 0)
							subList.putDescription(aProp, language.getLang());
						aProp = properties.getProperty(SchemeFactory.helpRoot + "." + indexCode
								+ "-" + language);
						if (aProp != null && aProp.length() > 0)
							subList.putHelp(Url.getConfigURL(properties, aProp), language.getLang());
					}
					String indexSQL = poolContext.substitute(aScheme,notationsDefinitions.get(indexCode));
					log.debug(indexSQL);
					try {
						ResultSet rs = execQuery(con,indexSQL);

						while (rs.next()) {
							String currCode = getAbout(aScheme,rs,"about");
							if (currCode == null) continue;

							String currIndex = rs.getLabel("notation");
							if (currIndex == null) {
								log
										.error(aScheme.getAbout()
												+ ": notation field is not returned by SQL query for notations="
												+ indexSQL);
								break;
							}

							Concept entry = aScheme.getConcept(currCode);
							if (entry == null) {
								String message = aScheme.getAbout() + SchemeInterface.separator + currCode
								+ " does not exist. Reffered for notation "
								+ currIndex;
								log.error(message);
								aScheme.getErrors().add(message);
							} else if (currIndex.length() > 0)
								entry.putNotation(indexCode,currIndex);
						}
						// close statement
						stmt.close();
					} catch (Exception ex) {
						String message = aScheme.getAbout() + ", SQL=" + indexSQL + " : " + ex.toString();
						log.error(message);
						aScheme.getErrors().add(message);
						Util.printStack(ex);
					}
				}
			}
		 */
		/****
			String aProp = null;
			if (referencesDefinitions.size() > 0) {
				for (String applicationCode : referencesDefinitions.keySet()) {
					String indexSQL = referencesDefinitions.get(applicationCode);
					log.debug(indexSQL);
					try {
						Statement stmt = con.createStatement();
						ResultSet rs = stmt.executeQuery(indexSQL);

						while (rs.next()) {
							String currCode = rs.getLabel("code");
							if (currCode == null || currCode.length() == 0) {
								log
										.error(schemeCode
												+ ": code field is not returned by SQL query for index="
												+ indexSQL);
								break;
							}
							if (currCode.startsWith(prefixToRemove))
								currCode = currCode.substring(prefixToRemove.length());
							String currApplication = rs.getLabel("application");
							if (currApplication == null) {
								log
										.error(schemeCode
												+ ": application field is not returned by SQL query for parents="
												+ indexSQL);
								break;
							}
							String currIndex = rs.getLabel("reference");
							if (currIndex == null) {
								log
										.error(schemeCode
												+ ": index field is not returned by SQL query for parents="
												+ indexSQL);
								break;
							}
							int currCount = rs.getInt("code");
							if (currCount == 0) {
								log
										.error(schemeCode
												+ ": count field is not returned by SQL query for index="
												+ indexSQL);
								break;
							}
							Concept entry = aScheme.getEntry(currCode);
							if (entry == null) {
								log.error(schemeCode + SchemeInterface.separator + currCode
										+ " does not exist. Reffered for application+index "
										+ currApplication + "+" + currIndex);
							} else if (currIndex.length() > 0)
								//TODO: Enregistre le d�compte
						}
						// close statement
						stmt.close();
					} catch (Exception ex) {
						log.error(schemeCode + ", SQL=" + indexSQL + " : ", ex);
					}
				}
			}

		 ***/
	}

	protected static Term getString (ConceptScheme scheme, BindingSet soln, String labelField, String defLang) {
		Binding nameBinding = soln.getBinding(labelField);
		if (nameBinding == null) return null;
		Value nameValue = nameBinding.getValue();
		if (nameValue == null) return null;
		if (nameValue instanceof Literal) {
			Literal nameLiteral = (Literal)nameValue;
			String aLabel = nameLiteral.getLabel();
			if (aLabel == null || aLabel.isEmpty()) return null;
			String aLang = nameLiteral.getLanguage();
			if (aLang == null || aLang.isEmpty()) {
				aLang = defLang;
			}
			return new Term(aLang,TermFormat.REGULAR, aLabel, null);
		} else if (nameValue instanceof URI) {
			URI nameURI = (URI)nameValue;
			String localCode = nameURI.getLocalName();
			if (localCode == null || localCode.isEmpty()) return null;
			String namespace = nameURI.getNamespace();
			if (scheme != null) {
				SkosManager skosManager = scheme.getManagerInstance();
				String schemeAbout = skosManager.findSchemeByURI(namespace);
				if (schemeAbout != null && !schemeAbout.isEmpty())
					return new Term (defLang, TermFormat.REL, schemeAbout+SchemeInterface.separator, null);
				else return new Term (defLang, TermFormat.URL, localCode, null);
			} else {
				return new Term (defLang, TermFormat.URL, localCode, null);
			}

		} else return null;
	}

	protected static Term getTerm (ConceptScheme scheme, BindingSet soln, String labelField, String defLang, String sourceField) {
		Term aTerm = getString(scheme,soln,labelField,defLang);
		if (aTerm != null) {
			if (sourceField != null && !sourceField.isEmpty()) {
				Term aSource = getString(scheme,soln,labelField,TermList.anyLanguage);
				if (aSource != null && !aSource.getValue().isEmpty()) {
					aTerm.setSource(aSource.getValue());
				}
			}
		}
		return aTerm;
	}

	protected static String getAbout(ConceptScheme scheme, BindingSet soln, String aboutField) {
		Term currResource = getString(scheme, soln, aboutField, TermList.anyLanguage);
		if (currResource != null) {
			String currCode = currResource.getValue();
			if (currCode == null || currCode.isEmpty()) {
				String message = scheme.getAbout()
				+ ": " + aboutField + " is empty for scheme"
				+ scheme.getAbout();
				SchemeFactory.log.error(message);
				scheme.getErrors().add(message);
			} else {
				currCode = scheme.getCleanAbout(currCode);
			}
			return currCode;
		} else {
			String message = aboutField+" field missing in SparQL result when loading scheme "+scheme.getAbout();
			SchemeFactory.log.error(message);
			scheme.getErrors().add(message);
			return null;
		}
	}
}
